package com.chat.app.config.shiro;

import com.chat.app.config.shiro.jwt.JwtToken;
import com.chat.app.mapper.TAppUserMapper;
import com.chat.app.utils.JwtUtil;
import com.chat.common.model.Constant;
import com.chat.common.utils.JedisUtil;
import com.chat.common.utils.StringUtil;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * 自定义Realm
 *
 * @author xiaoqiang
 * @date 2020/8/3 16:25
 */
@Service
public class UserRealm extends AuthorizingRealm {
    


    @Autowired
    private TAppUserMapper tAppUserMapper;


    /**
     * 大坑，必须重写此方法，不然Shiro会报错
     * @author xiaoqiang
     * @date 2020/8/3 16:25
     * @return boolean
     */
    @Override
    public boolean supports(AuthenticationToken authenticationToken) {
        return authenticationToken instanceof JwtToken;
    }

    /**
     * 只有当需要检测用户权限的时候才会调用此方法，例如checkRole,checkPermission之类的
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        String username = JwtUtil.getClaim(principalCollection.toString(), Constant.USERNAME);
        // 查询用户角色
//        List<Role> roles = roleMapper.findRoleByUsername(account);
//        Set<Integer> roleIds = new HashSet<>();
//        for (Role role : roles) {
//            if (role != null) {
//                // 添加角色
//                simpleAuthorizationInfo.addRole(role.getName());
//                // 根据用户角色查询权限
//                roleIds.add(role.getId());
//            }
//        }
//        Set<Permission> permissions = permissionMapper.findPermissionByRoleIds(roleIds);
//        for (Permission permission : permissions) {
//            if (permission != null) {
//                // 添加权限
//                simpleAuthorizationInfo.addStringPermission(permission.getPerCode());
//            }
//        }
        return simpleAuthorizationInfo;
    }

    /**
     * 默认使用此方法进行用户名正确与否验证，错误抛出异常即可。
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        String token = (String) authenticationToken.getCredentials();
        // 解密获得account，用于和数据库进行对比
        String username = JwtUtil.getClaim(token, Constant.USERNAME);
        // 帐号为空
        if (StringUtil.isBlank(username)) {
            throw new AuthenticationException("Token中帐号为空(The account in Token is empty.)");
        }
        // 查询用户是否存在
        // 开始认证，要AccessToken认证通过，且Redis中存在RefreshToken，且两个Token时间戳一致
        if (JwtUtil.verify(token) && JedisUtil.exists(Constant.PREFIX_SHIRO_REFRESH_TOKEN + username)) {
            //不需要校验用户名
//            User user = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getAccount, account));
//            if (user == null) {
//                throw new AuthenticationException("该帐号不存在(The account does not exist.)");
//            }
            // 获取RefreshToken的时间戳
            String currentTimeMillisRedis = JedisUtil.getObject(Constant.PREFIX_SHIRO_REFRESH_TOKEN + username).toString();
            // 获取AccessToken时间戳，与RefreshToken的时间戳对比
            if (JwtUtil.getClaim(token, Constant.CURRENT_TIME_MILLIS).equals(currentTimeMillisRedis)) {
                return new SimpleAuthenticationInfo(token, token, "userRealm");
            }
        }
        throw new AuthenticationException("Token已过期(Token expired or incorrect.)");
    }

}
